package com.csii.common;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.csii.adhoc.JdbcTemplate.DBType;
import com.csii.adhoc.JdbcTemplate.DataSourceConfig;
import com.csii.adhoc.JdbcTemplate.JdbcTemplateFactory;
import com.csii.adhoc.JdbcTemplate.PageHelperUtils;
import com.csii.adhoc.dblink.service.DbLinkService;
import com.csii.adhoc.dblink.DbLinkPo;
import com.csii.adhoc.exception.ParamValidityException;
import com.csii.adhoc.util.ParamCheckUtils;
import com.csii.result.PageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * @description: 连接外部数据库工具类
 * @author: panChuanJiang
 * @create: 2021-01-19 14:46
 */
@Component
@Slf4j
public class DbLinkUtils {

    @Autowired
    private JdbcTemplateFactory jdbcTemplateFactory;
    @Autowired
    private DbLinkService dbLinkService;

    /**
     * 获取外部连接sql的执行结构
     *
     * @param connid t_mgn_db表的连接id
     * @param sql    需要执行的sql
     * @return
     */
    public List<Map<String, Object>> getSqlResult(String connid, String sql) {
        JdbcTemplate jdbcTemplate = getJdbcTemplate(connid);
        log.info("connId:{},执行sql为{}", connid, sql);
        return jdbcTemplate.queryForList(sql);
    }

    /**
     * 获取外部连接的dbcTemplate对象
     *
     * @param connid t_mgn_db的连接id
     * @return
     */
    public JdbcTemplate getJdbcTemplate(String connid) {
        if (ParamCheckUtils.checkStringEmpty(connid)) {
            return null;
        }
        DbLinkPo dbLinkPo = dbLinkService.selectDbLinkByPrimaryKey(connid);
        if (dbLinkPo == null) {
            throw new ParamValidityException("该数据集id无记录，connId：" + connid);
        }
        return getJdbcTemplate(dbLinkPo);
    }

    /**
     * 分页查询
     *
     * @param connid   t_mgn_db表的连接id
     * @param sql      需要分页查询的sql
     * @param pageNo   需要查询的页码  从1开始
     * @param pageSize 一页包含几条数据
     * @return
     */
    public PageVo<Map<String, Object>> getPageSqlResult(String modelId,String connid, String sql, int pageNo, int pageSize) {
        DbLinkPo dbLinkPo = checkPageParams(connid, pageNo, pageSize);//检测参数合法性
        Page<Map<String, Object>> pageRes = new Page<>();
        JdbcTemplate jdbcTemplate = getJdbcTemplate(connid);
        DBType dbType = null;
        String driverClass = dbLinkPo.getDriverClass().toLowerCase();
        if (driverClass.contains("mysql")) {
            dbType = DBType.MYSQL;
        } else if (driverClass.contains("oracle")) {
            dbType = DBType.ORACLE;
        } else if (driverClass.contains("goldilocks")) {
            dbType = DBType.GOLDILOCKS;
        } else {
            throw new ParamValidityException("不支持的数据源类型");
        }
        log.info("当前的connId为:{}", connid);
        return PageVo.getPageVoFromIPage(PageHelperUtils.getPageResult(modelId,pageNo, pageSize, sql, dbType, jdbcTemplate));
    }

    private DbLinkPo checkPageParams(String connid, int start, int size) {
        if (ParamCheckUtils.checkStringEmpty(connid)) {
            throw new ParamValidityException("connid不能为空,connId:" + connid);
        }
        if (start <= 0 || size <= 0) {
            throw new ParamValidityException(String.format("分页参数不合法,必须大于0,start:%s,size:%s", start, size));
        }
        DbLinkPo dbLinkPo = dbLinkService.selectDbLinkByPrimaryKey(connid);
        if (dbLinkPo == null) {
            throw new ParamValidityException("该数据集id无记录,connId:" + connid);
        }
        return dbLinkPo;
    }

    private JdbcTemplate getJdbcTemplate(DbLinkPo dbLinkPo) {
        JdbcTemplate cacheBean = jdbcTemplateFactory.getCacheBean(dbLinkPo.getConnId());
        if (cacheBean != null) {
            return cacheBean;
        }
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        try {
            dataSourceConfig.setMaxActive(Integer.valueOf(dbLinkPo.getMaxActive()))
                    .setMinidle(Integer.valueOf(dbLinkPo.getMinidle()))
                    .setMaxConnectionSize(Integer.valueOf(dbLinkPo.getMaxConnectionSize()))
                    .setInitialSize(Integer.valueOf(dbLinkPo.getInitialSize()))
                    .setTestOnBorrow(Boolean.valueOf(dbLinkPo.getTestOnBorrow()))
                    .setTestOnReturn(Boolean.valueOf(dbLinkPo.getTestOnReturn()))
                    .setTestWhileIdle(Boolean.valueOf(dbLinkPo.getTestWhileIdle()))
                    .setTimeRunsMillis(Integer.valueOf(dbLinkPo.getTimeRunsMillis()))
                    .setMinTimeMillis(Integer.valueOf(dbLinkPo.getMinTimeMillis()))
                    .setPoolPreparedStatements(Boolean.valueOf(dbLinkPo.getPoolPreparedStatements()));
        } catch (Exception e) {
            log.error("连接池配置数据格式异常");
        }
        BeanUtils.copyProperties(dbLinkPo, dataSourceConfig);
        return jdbcTemplateFactory.getBean(dataSourceConfig);
    }
}
